/**
 * 
 */
package com.lincoln.framework.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * 该类自动支持所有实现了TreeType接口的类，可以根据输入数据进行自动树型对象的创建
 * 
 * @author 哨子
 * 
 */
public class TreeUtils {

    /**
     * 私有构造方法，避免生成对象
     */
    private TreeUtils() {
    }
    
    /**
     * 生成扁平化的元素列表，方便前端作为select显示
     * 1
     *   11
     *   12
     * 2 
     *   21
     *   22
     * 3 
     * @param elementList
     * @return
     */
    public static <T> List<? extends TreeType<T>> getflatTreeTypeList(List<? extends TreeType<T>> elementList) {
        return getflatTreeTypeList(elementList,null);
    }
    
    /**
     * 生成扁平化的元素列表，方便前端作为select显示
     * 1
     *   11
     *   12
     * 2 
     *   21
     *   22
     * 3 
     * @param elementList
     * @return
     */
    public static <T> List<? extends TreeType<T>> getflatTreeTypeList(List<? extends TreeType<T>> elementList,TreeTypeFilter<T> filter) {
        List<TreeType<T>> resultlist = new ArrayList<TreeType<T>>();
        if(elementList != null && elementList.size() > 0){
            for (TreeType<T> treeType : getTreeList(elementList)) {
                addFlatList(resultlist, treeType,filter);
            }
        }
        return resultlist;
    }
    
    /**
     * 此处使用泛型方法，自动进行类型转换
     * 
     * @param elementList
     * @return
     */
    public static <T> List<? extends TreeType<T>> getTreeList(List<? extends TreeType<T>> elementList) {
        if (elementList == null || elementList.size() == 0) {
            return elementList;
        }
        return getTree(elementList);
    }
    
    /**
     * 递归增加元素
     * @param resultlist
     * @param treeType
     */
    @SuppressWarnings("unchecked")
    private static <T>  void addFlatList(List<TreeType<T>> resultlist,TreeType<T> treeType,TreeTypeFilter<T> filter){
        if(filter != null && filter.isExclude(treeType)){
            return ;
        }
        resultlist.add(treeType);
        List<T> children = treeType.getChildren();
        if(children != null && children.size() > 0){
            for (T t : children) {
                addFlatList(resultlist, (TreeType<T>)t,filter);
            }
        }
    }

    /**
     * 首先针对元素进行分组，排序，将同一父节点的元素放置同一个分组，并且进行排序
     */
    private static <T> List<TreeType<T>> getTree(List<? extends TreeType<T>> elementList) {
        Map<Integer, List<TreeType<T>>> elementsMap = new HashMap<Integer, List<TreeType<T>>>();
        // 相同父ID的进行分组
        for (TreeType<T> treeType : elementList) {
            int parentId = treeType.getParentId();
            List<TreeType<T>> list = elementsMap.containsKey(parentId) ? elementsMap.get(parentId)
                    : new ArrayList<TreeType<T>>();
            list.add(treeType);
            elementsMap.put(parentId, list);
        }
        // 对分组后的列表进行排序，sort值越小排序越前
        for (List<TreeType<T>> treeTypeList : elementsMap.values()) {
            Collections.sort(treeTypeList, new Comparator<TreeType<T>>() {
                public int compare(TreeType<T> arg0, TreeType<T> arg1) {
                    return arg0.getSort() - arg1.getSort();
                }
            });
        }
        return buildTree(elementsMap, TreeType.ROOT_ELEMENT_ID, 1);
    }

    /**
     * 生成分类树
     * 
     * @param map
     * @param parentId
     * @param parentCode
     * @param level
     * @return
     */
    @SuppressWarnings("unchecked")
    private static <T> List<TreeType<T>> buildTree(Map<Integer, List<TreeType<T>>> map, int parentId, int level) {
        List<TreeType<T>> resultlist = null;
        if (map.containsKey(parentId)) {
            resultlist = map.get(parentId);
            for (TreeType<T> treeType : resultlist) {
                treeType.setLevel(level);
                treeType.setChildren((List<T>) buildTree(map, treeType.getId(), level + 1));
            }
        }
        return resultlist;
    }
}
